<template>
  <view 
    class="gesture-recognizer" 
    @touchstart="handleTouchStart"
    @touchmove="handleTouchMove"
    @touchend="handleTouchEnd"
    @touchcancel="handleTouchCancel"
  >
    <slot></slot>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue';

interface TouchPoint {
  x: number;
  y: number;
  timestamp: number;
}

interface GestureEvent {
  type: string;
  startPoint: TouchPoint;
  endPoint: TouchPoint;
  deltaX: number;
  deltaY: number;
  distance: number;
  duration: number;
  velocity: number;
}

interface Props {
  // 滑动阈值
  swipeThreshold?: number;
  // 长按时间阈值
  longPressThreshold?: number;
  // 双击时间间隔
  doubleTapInterval?: number;
  // 启用的手势类型
  enabledGestures?: string[];
}

interface Emits {
  (e: 'tap', event: GestureEvent): void;
  (e: 'doubleTap', event: GestureEvent): void;
  (e: 'longPress', event: GestureEvent): void;
  (e: 'swipeLeft', event: GestureEvent): void;
  (e: 'swipeRight', event: GestureEvent): void;
  (e: 'swipeUp', event: GestureEvent): void;
  (e: 'swipeDown', event: GestureEvent): void;
  (e: 'pinch', event: { scale: number; center: TouchPoint }): void;
  (e: 'rotate', event: { angle: number; center: TouchPoint }): void;
}

const props = withDefaults(defineProps<Props>(), {
  swipeThreshold: 50,
  longPressThreshold: 500,
  doubleTapInterval: 300,
  enabledGestures: () => ['tap', 'doubleTap', 'longPress', 'swipe'],
});

const emit = defineEmits<Emits>();

const startPoint = ref<TouchPoint | null>(null);
const endPoint = ref<TouchPoint | null>(null);
const longPressTimer = ref<number | null>(null);
const lastTapTime = ref(0);
const isLongPressed = ref(false);
const isSwiping = ref(false);

// 多点触控相关
const touches = ref<TouchPoint[]>([]);
const initialDistance = ref(0);
const initialAngle = ref(0);

const createTouchPoint = (touch: Touch): TouchPoint => ({
  x: touch.clientX,
  y: touch.clientY,
  timestamp: Date.now(),
});

const calculateDistance = (point1: TouchPoint, point2: TouchPoint): number => {
  const deltaX = point2.x - point1.x;
  const deltaY = point2.y - point1.y;
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
};

const calculateAngle = (point1: TouchPoint, point2: TouchPoint): number => {
  const deltaX = point2.x - point1.x;
  const deltaY = point2.y - point1.y;
  return Math.atan2(deltaY, deltaX) * 180 / Math.PI;
};

const getCenter = (touches: TouchPoint[]): TouchPoint => {
  const x = touches.reduce((sum, touch) => sum + touch.x, 0) / touches.length;
  const y = touches.reduce((sum, touch) => sum + touch.y, 0) / touches.length;
  return { x, y, timestamp: Date.now() };
};

const handleTouchStart = (e: TouchEvent) => {
  const touch = e.touches[0];
  const point = createTouchPoint(touch);
  
  startPoint.value = point;
  endPoint.value = null;
  isLongPressed.value = false;
  isSwiping.value = false;
  
  // 多点触控
  touches.value = Array.from(e.touches).map(createTouchPoint);
  
  if (e.touches.length === 2) {
    initialDistance.value = calculateDistance(touches.value[0], touches.value[1]);
    initialAngle.value = calculateAngle(touches.value[0], touches.value[1]);
  }
  
  // 长按检测
  if (props.enabledGestures.includes('longPress')) {
    longPressTimer.value = setTimeout(() => {
      if (startPoint.value && !isSwiping.value) {
        isLongPressed.value = true;
        const gestureEvent: GestureEvent = {
          type: 'longPress',
          startPoint: startPoint.value,
          endPoint: point,
          deltaX: 0,
          deltaY: 0,
          distance: 0,
          duration: Date.now() - startPoint.value.timestamp,
          velocity: 0,
        };
        emit('longPress', gestureEvent);
      }
    }, props.longPressThreshold);
  }
};

const handleTouchMove = (e: TouchEvent) => {
  if (!startPoint.value) return;
  
  const touch = e.touches[0];
  const point = createTouchPoint(touch);
  endPoint.value = point;
  
  const deltaX = point.x - startPoint.value.x;
  const deltaY = point.y - startPoint.value.y;
  const distance = calculateDistance(startPoint.value, point);
  
  // 如果移动距离超过阈值，取消长按
  if (distance > 10 && longPressTimer.value) {
    clearTimeout(longPressTimer.value);
    longPressTimer.value = null;
  }
  
  // 标记为滑动状态
  if (distance > props.swipeThreshold / 2) {
    isSwiping.value = true;
  }
  
  // 多点触控处理
  if (e.touches.length === 2) {
    const currentTouches = Array.from(e.touches).map(createTouchPoint);
    const currentDistance = calculateDistance(currentTouches[0], currentTouches[1]);
    const currentAngle = calculateAngle(currentTouches[0], currentTouches[1]);
    
    // 缩放手势
    if (props.enabledGestures.includes('pinch')) {
      const scale = currentDistance / initialDistance.value;
      const center = getCenter(currentTouches);
      emit('pinch', { scale, center });
    }
    
    // 旋转手势
    if (props.enabledGestures.includes('rotate')) {
      const angle = currentAngle - initialAngle.value;
      const center = getCenter(currentTouches);
      emit('rotate', { angle, center });
    }
  }
};

const handleTouchEnd = (e: TouchEvent) => {
  if (longPressTimer.value) {
    clearTimeout(longPressTimer.value);
    longPressTimer.value = null;
  }
  
  if (!startPoint.value || !endPoint.value) return;
  
  const deltaX = endPoint.value.x - startPoint.value.x;
  const deltaY = endPoint.value.y - startPoint.value.y;
  const distance = calculateDistance(startPoint.value, endPoint.value);
  const duration = endPoint.value.timestamp - startPoint.value.timestamp;
  const velocity = distance / duration;
  
  const gestureEvent: GestureEvent = {
    type: '',
    startPoint: startPoint.value,
    endPoint: endPoint.value,
    deltaX,
    deltaY,
    distance,
    duration,
    velocity,
  };
  
  // 判断手势类型
  if (!isLongPressed.value && !isSwiping.value) {
    // 点击手势
    if (props.enabledGestures.includes('tap')) {
      const currentTime = Date.now();
      const timeSinceLastTap = currentTime - lastTapTime.value;
      
      if (timeSinceLastTap < props.doubleTapInterval && props.enabledGestures.includes('doubleTap')) {
        // 双击
        gestureEvent.type = 'doubleTap';
        emit('doubleTap', gestureEvent);
        lastTapTime.value = 0; // 重置，避免三击被识别为双击
      } else {
        // 单击
        gestureEvent.type = 'tap';
        emit('tap', gestureEvent);
        lastTapTime.value = currentTime;
      }
    }
  } else if (distance > props.swipeThreshold && props.enabledGestures.includes('swipe')) {
    // 滑动手势
    const absX = Math.abs(deltaX);
    const absY = Math.abs(deltaY);
    
    if (absX > absY) {
      // 水平滑动
      if (deltaX > 0) {
        gestureEvent.type = 'swipeRight';
        emit('swipeRight', gestureEvent);
      } else {
        gestureEvent.type = 'swipeLeft';
        emit('swipeLeft', gestureEvent);
      }
    } else {
      // 垂直滑动
      if (deltaY > 0) {
        gestureEvent.type = 'swipeDown';
        emit('swipeDown', gestureEvent);
      } else {
        gestureEvent.type = 'swipeUp';
        emit('swipeUp', gestureEvent);
      }
    }
  }
  
  // 重置状态
  startPoint.value = null;
  endPoint.value = null;
  isLongPressed.value = false;
  isSwiping.value = false;
  touches.value = [];
};

const handleTouchCancel = () => {
  if (longPressTimer.value) {
    clearTimeout(longPressTimer.value);
    longPressTimer.value = null;
  }
  
  // 重置所有状态
  startPoint.value = null;
  endPoint.value = null;
  isLongPressed.value = false;
  isSwiping.value = false;
  touches.value = [];
};
</script>

<style lang="scss" scoped>
.gesture-recognizer {
  width: 100%;
  height: 100%;
  touch-action: none; // 禁用浏览器默认的触摸行为
}
</style>